﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace AlertSystem.PluggableModules
{
    public abstract class WorkingBaseTimer : WorkingBase
    {
        #region Properties and fields
        protected virtual int DUETIME { get { return 1000; } }
        protected virtual int PERIOD { get { return Timeout.Infinite; } }
        private object _lock = new object();
        protected bool Started { get; private set; }
        private Timer timer;
        private int syncPoint = 0;
        #endregion Properties and fields
        
        #region constructor
        public WorkingBaseTimer()
            : base()
        {
           
        }
        #endregion constructor

        #region Loop
        public virtual void Start()
        {
            lock (_lock)
            {
                Stop();
                Started = true;
                timer = new Timer(CycleLoop, null, 0, PERIOD);
            }
        }

        public virtual void Stop()
        {
            lock (_lock)
            {
                Started = false;
                if (timer != null)
                {
                    timer.Dispose();
                }
            }
        }
        
        protected virtual void ChangeTimer(int dueTime, int period)
        {
            if (timer != null)
            {
                timer.Change(dueTime, period);
            }
        }

        private void CycleLoop(object state)
        {
            int sync = Interlocked.CompareExchange(ref syncPoint, 1, 0);
            if (sync == 0)
            {
                try
                {
                    LoopWorking();
                }
                catch (Exception ex)
                {
                    HandleException(ex);
                }
                finally
                {
                    ChangeTimer(DUETIME, PERIOD);
                    syncPoint = 0;
                }
            }
        }

        protected abstract void LoopWorking();
        #endregion Loop
    }
}
